package finc_single_num;
/*
给定一个整数数组 nums，其中恰好有两个元素只出现一次，其余所有元素均出现两次。 找出只出现一次的那两个元素。
[2,5,8,2,5,7],8和7只出现一次，2，5成对出现

第一步：先用x和y来代表只出现一次的两个数字。
求出所有数的异或的结果，这里相同的两个数将异或成0，而任何数和0异或结果不变，既 z^0=z,结果就是:
2^5^x^2^5^y = x^y = bitmask,求得的bitmask保留了x和y不一样的位，但是还不能求得x或者y

第二步：bitmask最右边的一位1保留，其他位都置为0，得到一个diff ，计算方法为：diff= bitmask & (-bitmask)
假如bitmask=48，
     48 = 0011 0000
    -48 = 1011 0000
因为与操作的两个数一定有一个数是负数，负数在计算机中是以它的补码形式存储的，补码 = 反码 +1，我们先来计算反码，反码 = 源码除了符号位不变，其他都置反。
假如最右边一位1处在右数第N位，则反码的第N位右边全1，补码+1的时候，不断向左进位，直到进位到第N位，所以补码的第N位肯定也为1，其他位都跟源码相反，
这左边的M位数，符号位是取负数的时候反过来的，其他位是取反码的时候反过来的。右侧的几位和原来一样但都是0。这样和原来与操作就只会留下第N位的1

我们以-48=1011 0000 举例求补码：
源码：1011 0000  反码 1100 1111 补码 1101 0000，计算bitmask & (-bitmask)实际上不会用0011 0000（48）跟1011 0000（-48）与操作，
而是和补码与操作：
0011 0000（48） & 1101 0000（-48的补码） = 0001 0000 = diff，这样diff就只保留了最右边的1，其他全部为0


第三步：
这个diff只有一位是1，且这一位要么来自x要么来自y。(其实我们可以保留bitmask任何一个为1的位得到diff，而不一定是最右边的，第二步这么求只是因为简单）
重新计算每个数与上diff，如果结果!=0，表示该数的该位也为1（那么就有可能是x或者y），那么保留这个数，就把y排除在外了（当然还包括那些该位不为1的那些数），
，剩下的数异或在一起，其中相等的两个数异或会得到0，结果就是x和0进行异或的结果：
2^5^x^2^5=x^0=x,（这里我们假设2和5的第N位都是1，无论有多少相同的，都会被自身异或成0），所以我们求得了x

第四步：
因为x ^ y = bitmask,这里我们已经计算得到了x，通过 x ^ bitmask 就能得到y

该算法求得的x和y，并不会保留他们在数组中的先后次序，因而我们一直将该数假设成x或者y

 */